/*	
*	File: ip_hdrincl-option.h
*	Date: 2011/11/06
*	User: Ronmaru
*	Desctiption: IP_HDRINCL option description
*/

#ifndef IP_HDRINCL_OPTION_H
#define IP_HDRINCL_OPTION_H

#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/socket_types.hpp>

using namespace boost;
using namespace asio;

class ip_hdrincl
{
public:
  // Default constructor.
  ip_hdrincl()
    : value_(0)
  {
  }

  // Construct with a specific option value.
  explicit ip_hdrincl(int v)
    : value_(v)
  {
  }

  // Set the value of the option.
  ip_hdrincl& operator=(int v)
  {
    value_ = v;
    return *this;
  }

  // Get the current value of the option.
  int value() const
  {
    return value_;
  }

  // Get the level of the socket option.
  template <typename Protocol>
  int level(const Protocol& protocol) const
  {
    if (protocol.family() == PF_INET6)
      return IPPROTO_IP;
    return IPPROTO_IP;
  }

  // Get the name of the socket option.
  template <typename Protocol>
  int name(const Protocol& protocol) const
  {
    if (protocol.family() == PF_INET6)
      return IP_HDRINCL;
    return IP_HDRINCL;
  }

  // Get the address of the data.
  template <typename Protocol>
  int* data(const Protocol&)
  {
    return &value_;
  }

  // Get the address of the data.
  template <typename Protocol>
  const int* data(const Protocol&) const
  {
    return &value_;
  }

  // Get the size of the data.
  template <typename Protocol>
  std::size_t size(const Protocol&) const
  {
    return sizeof(value_);
  }

  // Set the size of the data.
  template <typename Protocol>
  void resize(const Protocol&, std::size_t s)
  {
    if (s != sizeof(value_))
    {
      std::length_error ex("ip_hdrincl change error");
      boost::throw_exception(ex);
    }
#if defined(__hpux)
    if (value_ < 0)
      value_ = value_ & 0xFF;
#endif
  }

private:
  int value_;
};

#endif